package com.wang.myreflect;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

/**
 * 获取成员方法
 * @author yandong
 */
public class MyReflectDemo4 {
    public static void main(String[] args) throws Exception{
        /*
         * Class类中用于获取成员方法的方法:
         * 1. Method[] getMethods(): 返回所有公共成员方法对象的数组, 包括继承的 (父类中的所有public方法)
         * 2. Method[] getDeclaredMethods(): 返回所有成员方法对象的数组, 不包括继承的
         * 3. Method getMethod(String name, Class<?>... parameterTypes): 返回单个公共成员方法对象
         * 4. Method getDeclaredMethod(String name, Class<?>... parameterTypes): 返回单个成员方法对象
         *
         * Method类中用于调用方法的方法:
         * Object invoke(Object obj, Object... args): 运行方法
         * 参数一: 用obj对象调用该方法
         * 参数二: 调用方法的传递的参数 (如果没有就不写)
         * 返回值: 方法的返回值 (如果没有就不写)
         */

        // 1.获取 Student的字节码文件class对象
        Class clazz = Class.forName("com.wang.myreflect.Student");

        // 2.获取所有public成员方法 (包含父类中的)
        Method[] methods1 = clazz.getMethods();
        for (Method method : methods1) {
            System.out.println(method);
        }

        System.out.println("===========================");

        // 3. 获取本类所有方法 (不包含父类中的方法)
        Method[] methods2 = clazz.getDeclaredMethods();
        for (Method method : methods2) {
            System.out.println(method);
        }

        System.out.println("===========================");

        // 4. 获取单个public成员方法
        Method method1 = clazz.getMethod("study");
        System.out.println(method1);
        Method method2 = clazz.getMethod("study", String.class);
        System.out.println(method2);

        System.out.println("===========================");

        // 5. 获取单个本类方法 (不包含父类中的方法)
        Method method3 = clazz.getDeclaredMethod("eat", String.class);
        System.out.println(method3);

        System.out.println("===========================");

        // 6. 获取方法的权限修饰符
        int modifiers = method3.getModifiers();
        System.out.println(modifiers); // 2 -> private

        System.out.println("===========================");

        // 7. 获取方法名字
        String name = method3.getName();
        System.out.println(name);

        System.out.println("===========================");

        // 8. 获取方法形参
        Parameter[] parameters = method3.getParameters();
        for (Parameter parameter : parameters) {
            System.out.println(parameter);
        }

        System.out.println("===========================");

        // 9. 获取方法抛出的异常类型
        Class<?>[] exceptionTypes = method3.getExceptionTypes();
        for (Class<?> exceptionType : exceptionTypes) {
            System.out.println(exceptionType);
        }

        System.out.println("===========================");

        // 10. 运行方法
        /*
         * Object invoke (Object obj, Object... args): 运行方法
         * - 参数一: 用obj对象调用该方法
         * - 参数二: 调用方法的传递的参数 (如果没有就不写)
         * - 返回值: 方法的返回值 (如果没有就不写)
         */

        Student stu = new Student("Tom", 12);
        method3.setAccessible(true); // 临时取消权限校验
        String result = (String) method3.invoke(stu, "汉堡");
        System.out.println(result);

    }
}
